import numpy as np
import os
import matplotlib.pyplot as plt
from AHP_code import AHPModel

def parse_kano_result(file_path: str) -> dict:
    """解析kano_result.txt文件，提取属性的满意度和不满意度系数"""
    kano_results = {}
    current_attr = None
    
    with open(file_path, "r", encoding="utf-8") as f:
        lines = f.readlines()
    
    for line in lines:
        line = line.strip()
        if line.startswith("属性:"):
            current_attr = line.split(": ")[1].strip()
            kano_results[current_attr] = {}
        elif line.startswith("满意度系数:"):
            value = float(line.split(": ")[1].strip())
            kano_results[current_attr]["satisfaction"] = value
        elif line.startswith("不满意度系数:"):
            value = float(line.split(": ")[1].strip())
            kano_results[current_attr]["dissatisfaction"] = value
    
    return kano_results

def save_visualizations(criteria_names, criteria_weights, combined_weights, alternatives, output_dir):
    """保存AHP分析的可视化结果"""
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 1. 绘制AHP原始权重对比图
    plt.figure(figsize=(12, 6))
    bars = plt.bar(criteria_names, criteria_weights, color='skyblue')
    plt.title('AHP原始准则权重')
    plt.xlabel('准则')
    plt.ylabel('权重')
    plt.xticks(rotation=45, ha='right')
    plt.tight_layout()
    
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height,
                 f'{height:.4f}', ha='center', va='bottom')
    
    plt.savefig(os.path.join(output_dir, 'ahp_original_weights.png'))
    plt.close()
    
    # 2. 绘制结合Kano的调整权重图
    plt.figure(figsize=(12, 6))
    bars = plt.bar(criteria_names, combined_weights, color='lightgreen')
    plt.title('结合Kano满意度的调整权重')
    plt.xlabel('准则')
    plt.ylabel('权重')
    plt.xticks(rotation=45, ha='right')
    plt.tight_layout()
    
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height,
                 f'{height:.4f}', ha='center', va='bottom')
    
    plt.savefig(os.path.join(output_dir, 'combined_weights.png'))
    plt.close()
    
    # 3. 绘制方案对比雷达图
    labels = criteria_names
    num_labels = len(labels)
    
    alternatives = np.append(alternatives, [alternatives[0][:]], axis=0)
    angles = np.linspace(0, 2*np.pi, num_labels, endpoint=False).tolist()
    angles += angles[:1]
    
    plt.figure(figsize=(8, 8))
    ax = plt.subplot(111, polar=True)
    
    values = alternatives[0].tolist()
    values += values[:1]
    ax.plot(angles, values, 'o-', linewidth=2, label='AI惠山泥人')
    ax.fill(angles, values, alpha=0.25)
    
    values = alternatives[1].tolist()
    values += values[:1]
    ax.plot(angles, values, 's-', linewidth=2, label='传统惠山泥人')
    ax.fill(angles, values, alpha=0.25)
    
    ax.set_thetagrids(np.degrees(angles[:-1]), labels)
    ax.set_ylim(0, 10)
    plt.title('方案对比雷达图')
    plt.legend(loc='upper right')
    plt.tight_layout()
    
    plt.savefig(os.path.join(output_dir, 'alternatives_comparison.png'))
    plt.close()

def save_ahp_results(criteria_names, criteria_weights, combined_weights, alternatives, composite_score, output_dir):
    """保存AHP分析结果到文本文件"""
    output_path = os.path.join(output_dir, "AHP_result.txt")
    
    with open(output_path, "w", encoding="utf-8") as f:
        f.write("="*50 + "\n")
        f.write("AHP层次分析法分析结果\n")
        f.write("="*50 + "\n\n")
        
        f.write("="*20 + " AHP原始准则权重 " + "="*20 + "\n")
        for attr, w in zip(criteria_names, criteria_weights):
            f.write(f"{attr}: {w:.4f}\n")
        f.write("\n")
        
        f.write("="*20 + " 结合Kano满意度的调整权重 " + "="*20 + "\n")
        for attr, w in zip(criteria_names, combined_weights):
            f.write(f"{attr}: {w:.4f}\n")
        f.write("\n")
        
        f.write("="*20 + " 方案评分矩阵 " + "="*20 + "\n")
        f.write("\t" + "\t".join(criteria_names) + "\n")
        for i, alt in enumerate(alternatives):
            alt_name = ['AI惠山泥人', '传统惠山泥人'][i]
            f.write(f"{alt_name}\t" + "\t".join([f"{score}" for score in alt]) + "\n")
        f.write("\n")
        
        f.write("="*20 + " 综合得分 " + "="*20 + "\n")
        for i, score in enumerate(composite_score):
            alt_name = ['AI惠山泥人', '传统惠山泥人'][i]
            f.write(f"{alt_name}: {score:.4f}\n")
        f.write("\n")
        
        f.write("="*20 + " 方案优先级 " + "="*20 + "\n")
        ranking = sorted(enumerate(composite_score), key=lambda x: x[1], reverse=True)
        for i, (idx, score) in enumerate(ranking, 1):
            f.write(f"{i}. {['AI惠山泥人', '传统惠山泥人'][idx]}: {score:.4f}\n")
    
    print(f"AHP分析结果已保存到 {output_path}")

def print_ahp_results(criteria_names, criteria_weights, combined_weights, alternatives, composite_score):
    """打印AHP分析结果到命令行"""
    print("\n" + "="*50)
    print("AHP层次分析法分析结果")
    print("="*50)
    
    print("\n" + "="*20 + " AHP原始准则权重 " + "="*20)
    for attr, w in zip(criteria_names, criteria_weights):
        print(f"{attr}: {w:.4f}")
    
    print("\n" + "="*20 + " 结合Kano满意度的调整权重 " + "="*20)
    for attr, w in zip(criteria_names, combined_weights):
        print(f"{attr}: {w:.4f}")
    
    print("\n" + "="*20 + " 方案评分矩阵 " + "="*20)
    print("\t" + "\t".join(criteria_names))
    for i, alt in enumerate(alternatives):
        alt_name = ['AI惠山泥人', '传统惠山泥人'][i]
        print(f"{alt_name}\t" + "\t".join([f"{score}" for score in alt]))
    
    print("\n" + "="*20 + " 综合得分 " + "="*20)
    for i, score in enumerate(composite_score):
        alt_name = ['AI惠山泥人', '传统惠山泥人'][i]
        print(f"{alt_name}: {score:.4f}")
    
    print("\n" + "="*20 + " 方案优先级 " + "="*20)
    ranking = sorted(enumerate(composite_score), key=lambda x: x[1], reverse=True)
    for i, (idx, score) in enumerate(ranking, 1):
        print(f"{i}. {['AI惠山泥人', '传统惠山泥人'][idx]}: {score:.4f}")

def analyze_matrix_consistency(matrix):
    """分析判断矩阵的一致性问题并提供调整建议"""
    n = len(matrix)
    from numpy.linalg import eig
    
    eigenvalues, _ = eig(matrix)
    max_eigenvalue = max(eigenvalues).real
    CI = (max_eigenvalue - n) / (n - 1)
    RI_dict = {1: 0, 2: 0, 3: 0.58, 4: 0.90, 5: 1.12, 
               6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45}
    CR = CI / RI_dict.get(n, 0)
    
    print(f"矩阵一致性指标:")
    print(f"最大特征值: {max_eigenvalue:.4f}")
    print(f"CI: {CI:.4f}, CR: {CR:.4f}")
    
    if CR >= 0.1:
        print("\n⚠️ 矩阵一致性不足，建议调整以下元素:")
        # 找出最不一致的元素
        max_inconsistency = 0
        i_max, j_max, k_max = 0, 0, 0
        
        for i in range(n):
            for j in range(i+1, n):
                for k in range(n):
                    if i != k and j != k:
                        # 检查传递性：a_ij * a_jk ≈ a_ik
                        ratio = matrix[i, j] * matrix[j, k] / matrix[i, k]
                        inconsistency = abs(ratio - 1)
                        
                        if inconsistency > max_inconsistency:
                            max_inconsistency = inconsistency
                            i_max, j_max, k_max = i, j, k
        
        print(f"- 最大不一致性在: a{i_max+1}{j_max+1}={matrix[i_max, j_max]:.2f}, a{j_max+1}{k_max+1}={matrix[j_max, k_max]:.2f}, a{i_max+1}{k_max+1}={matrix[i_max, k_max]:.2f}")
        print(f"  建议调整: a{i_max+1}{j_max+1} 或 a{j_max+1}{k_max+1} 或 a{i_max+1}{k_max+1}")
        
        print("\n调整建议:")
        print("1. 确保矩阵满足互反性: matrix[i,j] = 1/matrix[j,i]")
        print("2. 检查传递性: 若A比B重要，B比C重要，则A应比C更重要")
        print("3. 避免极端值(如9或1/9)，除非确有充分理由")
        return False
    
    print("✅ 矩阵一致性良好，可以继续分析")
    return True

def main():
    """结合Kano结果与AHP模型进行分析"""
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    KANO_RESULT_FILE = os.path.join(BASE_DIR, "result/kano_result.txt")
    AHP_OUTPUT_DIR = os.path.join(BASE_DIR, "result_AHP")
    
    kano_data = parse_kano_result(KANO_RESULT_FILE)
    
    if not kano_data:
        print("警告：未找到Kano分析结果文件或解析失败")
        return
    
    # 从Kano结果中提取属性列表
    criteria_names = list(kano_data.keys())
    
    # 构建准则层判断矩阵（调整后版本）
    criteria_matrix = np.array([
        [1, 2, 4, 1/3, 1/4, 1/5, 1/6, 1/5],   # 易用性
        [1/2, 1, 3, 1/4, 1/5, 1/6, 1/7, 1/6],   # 性能
        [1/4, 1/3, 1, 1/5, 1/6, 1/7, 1/8, 1/7],   # 价格
        [3, 4, 5, 1, 2, 3, 4, 4],              # 设计
        [4, 5, 6, 1/2, 1, 2, 3, 3],            # 可靠性
        [5, 6, 7, 1/3, 1/2, 1, 2, 2],           # 安全性
        [6, 7, 8, 1/4, 1/3, 1/2, 1, 1],         # 扩展性
        [5, 6, 7, 1/4, 1/3, 1/2, 1, 1],         # 用户体验
    ])
    
    # 分析矩阵一致性并提供调整建议
    if not analyze_matrix_consistency(criteria_matrix):
        print("\n请调整判断矩阵后重新运行")
        return
    
    # 初始化AHP模型
    ahp = AHPModel(criteria_names)
    ahp.set_criteria_matrix(criteria_matrix)
    
    # 检查一致性
    if not ahp.is_consistent():
        print("准则层判断矩阵未通过一致性检验，请根据上述建议调整")
        return
    
    # 获取权重
    criteria_weights = ahp.get_weights()
    
    # 结合Kano满意度调整权重
    kano_satisfaction = np.array([kano_data[attr]["satisfaction"] for attr in criteria_names])
    kano_weights = kano_satisfaction / kano_satisfaction.sum()
    combined_weights = criteria_weights * kano_weights
    combined_weights /= combined_weights.sum()
    
    # 方案评分矩阵
    alternatives = [
        [7, 8, 6, 9, 8, 7, 9, 8],  # AI惠山泥人
        [5, 4, 7, 6, 5, 6, 4, 5]   # 传统惠山泥人
    ]
    
    # 计算综合得分
    composite_score = np.dot(alternatives, combined_weights)
    
    # 输出结果
    print_ahp_results(criteria_names, criteria_weights, combined_weights, alternatives, composite_score)
    save_ahp_results(criteria_names, criteria_weights, combined_weights, alternatives, composite_score, AHP_OUTPUT_DIR)
    save_visualizations(criteria_names, criteria_weights, combined_weights, alternatives, AHP_OUTPUT_DIR)
    
    print(f"\n可视化结果已保存到 {AHP_OUTPUT_DIR} 文件夹")

if __name__ == "__main__":
    main()